package cn.o.app.db;

import java.util.List;

import android.os.AsyncTask;
import cn.o.app.event.Listener;
import cn.o.app.queue.QueueItem;

@SuppressWarnings("unchecked")
public class DbTask<INPUT, OUTPUT> extends QueueItem<IDbTask<INPUT, OUTPUT>>
		implements IDbTask<INPUT, OUTPUT> {

	protected INPUT mInput;

	protected OUTPUT mOutput;

	protected DbAsyncTask mTask;

	public void addListener(DbTaskListener<INPUT, OUTPUT> listener) {
		super.addListener(listener);
	}

	@Override
	public INPUT getInput() {
		return mInput;
	}

	@Override
	public void setInput(INPUT input) {
		if (mStarted || mStoped) {
			return;
		}
		mInput = input;
	}

	@Override
	public OUTPUT getOutput() {
		return mOutput;
	}

	@Override
	public void setOutput(OUTPUT output) {
		if (mStarted || mStoped) {
			return;
		}
		mOutput = output;
	}

	@Override
	public boolean start() {
		boolean result = super.start();
		if (result) {
			this.mTask = new DbAsyncTask();
			this.mTask.execute();
		}
		return result;
	}

	@Override
	public boolean stop() {
		boolean result = super.stop();
		if (result) {
			if (this.mOutput == null) {
				if (this.mTask != null) {
					this.mTask.cancel(true);
				}
			}
		}
		return result;
	}

	class DbAsyncTask extends AsyncTask<String, Integer, Object> {

		protected Object doInBackground(String... paramters) {
			try {
				OUTPUT output = null;
				List<Listener> listeners = getListeners();
				for (Listener listener : listeners) {
					if (listener instanceof IDbTaskListener) {
						IDbTaskListener<INPUT, OUTPUT> targetListener = (IDbTaskListener<INPUT, OUTPUT>) listener;
						output = targetListener.doInBackground(DbTask.this,
								getInput());
						if (output != null) {
							break;
						}
					}
				}
				setOutput(output);
				return output;
			} catch (Exception e) {
				return e;
			}
		}

		protected void onPostExecute(Object object) {
			List<Listener> listeners = getListeners();
			for (Listener listener : listeners) {
				if (listener instanceof IDbTaskListener) {
					IDbTaskListener<INPUT, OUTPUT> targetListener = (IDbTaskListener<INPUT, OUTPUT>) listener;
					if (object == null) {
						targetListener.onException(DbTask.this,
								new NullPointerException());
					} else if (object instanceof Exception) {
						targetListener.onException(DbTask.this,
								(Exception) object);
					} else {
						targetListener.onComplete(DbTask.this,
								DbTask.this.getOutput());
					}
				}
			}
			stop();
		}
	}
}
